﻿using Microsoft.AspNetCore.Mvc;
using NPOI.SS.Formula.Functions;
using Senparc.CO2NET.HttpUtility;
using Senparc.CO2NET.Utilities;
using Senparc.Weixin;
using Senparc.Weixin.Exceptions;
using Senparc.Weixin.Helpers;
using Senparc.Weixin.TenPayV3;
using Senparc.Weixin.TenPayV3.Apis;
using Senparc.Weixin.TenPayV3.Apis.BasePay;
using Senparc.Weixin.TenPayV3.Apis.Entities;
using Senparc.Weixin.TenPayV3.Entities;
using Senparc.Weixin.TenPayV3.Helpers;
using System.Collections.Concurrent;
using System.Text;

namespace Web.Controllers
{
    public class JSAPIPayController : BaseController
    {

        public IActionResult Index()
        {
            return View();
        }

        private static TenPayV3Info _tenPayV3Info;

        public static TenPayV3Info TenPayV3Info
        {
            get
            {
                if (_tenPayV3Info == null)
                {
                    var key = TenPayHelper.GetRegisterKey(Config.SenparcWeixinSetting);

                    _tenPayV3Info =
                        TenPayV3InfoCollection.Data[key];
                }
                return _tenPayV3Info;
            }
        }

        /// <summary>
        /// 用于初始化BasePayApis
        /// </summary>
        private readonly ISenparcWeixinSettingForTenpayV3 _tenpayV3Setting;

        private readonly BasePayApis _basePayApis;
        private readonly SenparcHttpClient _httpClient;

        /// <summary>
        /// trade_no 和 transaction_id 对照表
        /// TODO：可以放入缓存，设置有效时间
        /// </summary>
        public static ConcurrentDictionary<string, string> TradeNumberToTransactionId = new ConcurrentDictionary<string, string>();


        public JSAPIPayController(SenparcHttpClient httpClient)
        {
            _tenpayV3Setting = Senparc.Weixin.Config.SenparcWeixinSetting.TenpayV3Setting;
            _basePayApis = new BasePayApis(_tenpayV3Setting);
            this._httpClient = httpClient;
        }

        public async Task<IActionResult> JsApi()
        {
            try
            {
               
                var openId = CurrentUserOpenid;
             
                //生成订单10位序列号，此处用时间和随机数生成，商户根据自己调整，保证唯一
                 string  sp_billno = string.Format("{0}{1}{2}", Config.SenparcWeixinSetting.TenPayV3_MchId/*10位*/, SystemTime.Now.ToString("yyyyMMddHHmmss"),
                        TenPayV3Util.BuildRandomStr(6));
               //调用下单接口下单
                var name = "test";
                var price = 100;//单位：分
                var notifyUrl = TenPayV3Info.TenPayV3Notify;

                //请求信息
                TransactionsRequestData jsApiRequestData = new(Config.SenparcWeixinSetting.TenPayV3_AppId, Config.SenparcWeixinSetting.TenPayV3_MchId, name + " - 微信支付 V3", sp_billno, new TenpayDateTime(DateTime.Now.AddHours(1), false), null, notifyUrl, null, new() { currency = "CNY", total = price }, new(openId), null, null, null);

                //请求接口
                var basePayApis2 = new Senparc.Weixin.TenPayV3.TenPayHttpClient.BasePayApis2(_httpClient, _tenpayV3Setting);
                var result = await basePayApis2.JsApiAsync(jsApiRequestData);

                if (result.VerifySignSuccess != true)
                {
                    throw new WeixinException("获取 prepay_id 结果校验出错！");
                }

                //获取 UI 信息包
                var jsApiUiPackage = TenPaySignHelper.GetJsApiUiPackage(TenPayV3Info.AppId, result.prepay_id,null);
                //临时记录订单信息，留给退款申请接口测试使用（分布式情况下请注意数据同步）
                //HttpContext.Session.SetString("BillNo", sp_billno);
                //HttpContext.Session.SetString("BillFee", price.ToString());

                return Json(new {code=0,data= jsApiUiPackage});
            }
            catch (Exception ex)
            {
                LogHelper.Error("错误消息" + ex);
                Senparc.Weixin.WeixinTrace.BaseExceptionLog(ex);
                throw;
            }
        }

        /// <summary>
        /// JS-SDK支付回调地址（在下单接口中设置的 notify_url）
        /// </summary>
        /// <returns></returns>
        public async Task<IActionResult> PayNotifyUrl()
        {
            try
            {
                //获取微信服务器异步发送的支付通知信息
                var resHandler = new TenPayNotifyHandler(HttpContext);
                var orderReturnJson = await resHandler.AesGcmDecryptGetObjectAsync<OrderReturnJson>();
                //获取支付状态
                string trade_state = orderReturnJson.trade_state;

                //验证请求是否从微信发过来（安全）
                NotifyReturnData returnData = new();

                //验证可靠的支付状态
                if (orderReturnJson.VerifySignSuccess == true && trade_state == "SUCCESS")
                {
                    returnData.code = "SUCCESS";//正确的订单处理
                    /* 提示：
                        * 1、直到这里，才能认为交易真正成功了，可以进行数据库操作，但是别忘了返回规定格式的消息！
                        * 2、上述判断已经具有比较高的安全性以外，还可以对访问 IP 进行判断进一步加强安全性。
                        * 3、下面演示的是发送支付成功的模板消息提示，非必须。
                        */

                   
                }
                else
                {
                    returnData.code = "FAILD";//错误的订单处理
                    returnData.message = "验证失败";

                    //此处可以给用户发送支付失败提示等
                }

        
                return Json(returnData);
            }
            catch (Exception ex)
            {
                WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex));
                throw;
            }
        }
    }
}
